<template>
  <div class="graph-container">
    <a-card title="X6 图形编辑器" :bordered="false">
      <template #extra>
        <Toolbar 
          :drawerVisible="drawerVisible"
          :canUndo="canUndo"
          :canRedo="canRedo"
          @toggle-drawer="toggleDrawer"
          @add-node="addNode"
          @add-edge="addEdge"
          @select-all="selectAll"
          @clear-selection="clearSelection"
          @delete-selected="deleteSelected"
          @clear-graph="clearGraph"
          @undo="undo"
          @redo="redo"
          @center-content="centerContent"
          @zoom-in="zoomIn"
          @zoom-out="zoomOut"
          @reset-zoom="resetZoom"
                     @export-svg="exportSVG"
           @export-png="exportPNG"
           @export-jpeg="exportJPEG"
           @auto-layout="autoLayout"
           @horizontal-layout="horizontalLayout"
           @vertical-layout="verticalLayout"
           @tree-layout="treeLayout"
           @circular-layout="circularLayout"
           @grid-layout="gridLayout"
           @serialize="serializeGraph"
          @import="openImportDialog"
           @go-home="goHome"
           @show-shortcuts="showShortcuts"
        />
      </template>
      
      <StatusBar 
        :currentZoom="currentZoom"
        :selectedCount="selectedCount"
        :isDragging="isDragging"
        :dragType="dragType"
        :canUndo="canUndo"
        :canRedo="canRedo"
      />
      

      
             <div id="graph-container" style="width: 100%; height: 600px; border: 1px solid #d9d9d9; position: relative;"></div>
    </a-card>

    <!-- 左侧元素抽屉 -->
    <ElementDrawer
      :visible="drawerVisible"
      :currentEdgeType="currentEdgeType"
      @close="drawerVisible = false"
      @add-node="addNodeByType"
      @set-edge-type="setEdgeType"
      @add-random-node="addNode"
      @add-edge="addEdge"
      @center-content="centerContent"
      @reset-zoom="resetZoom"
    />

    <!-- 节点选择器弹出层 -->
    <NodeSelector
      :visible="nodeSelectorVisible"
      :position="nodeSelectorPosition"
      @select="onNodeSelected"
      @close="closeNodeSelector"
    />

    <!-- 位置选择器弹出层 -->
    <div v-if="showLocationSelector" class="location-selector-overlay" @click="closeLocationSelector">
      <div class="location-selector" @click.stop :style="locationSelectorStyle">
        <div class="selector-header">
          <span class="selector-title">选择添加位置</span>
        </div>
        <div class="selector-content">
          <div class="selector-item" @click="selectAddToGroup">
            <div class="item-icon group-icon"></div>
            <span class="item-text">添加到组内</span>
          </div>
          <div class="selector-item" @click="selectAddToOutside">
            <div class="item-icon outside-icon"></div>
            <span class="item-text">添加到组外</span>
          </div>
        </div>
      </div>
    </div>

    <!-- 节点配置对话框 -->
    <NodeConfigDialog
      :visible="nodeConfigDialogVisible"
      :nodeData="currentNodeData"
      :position="nodeConfigPosition"
      :graphManager="graphManager"
      :businessData="businessData"
      @save="onNodeConfigSave"
      @cancel="closeNodeConfigDialog"
    />

    <!-- 导入对话框 -->
    <ImportDialog
      :visible="importDialogVisible"
      @import="handleImport"
      @cancel="closeImportDialog"
    />

  </div>
</template>

<script>
import Toolbar from './components/Toolbar.vue'
import StatusBar from './components/StatusBar.vue'
import ElementDrawer from './components/ElementDrawer.vue'
import NodeSelector from './components/NodeSelector.vue'
import NodeConfigDialog from './components/NodeConfigDialog.vue'
import ImportDialog from './components/ImportDialog.vue'
import { GraphManager } from './utils/graphManager'
import { KeyboardManager } from './utils/keyboardManager'
import { DragManager } from './utils/dragManager'
import { LayoutManager } from './utils/layoutManager'
import { SampleData } from './utils/sampleData'
import { PORT_CONFIG, NodeConfig } from './utils/nodeConfig'
import { EdgeConfig } from './utils/edgeConfig'

export default {
  name: 'Graph',
  components: {
    Toolbar,
    StatusBar,
    ElementDrawer,
    NodeSelector,
    NodeConfigDialog,
    ImportDialog
  },
  data() {
    return {
      graphManager: null,
      keyboardManager: null,
      dragManager: null,
      layoutManager: null,
      drawerVisible: true,
      currentEdgeType: 'normal',
      isDragging: false,
      dragType: '',
      canUndo: false,
      canRedo: false,
      // 节点选择器相关状态
      nodeSelectorVisible: false,
      nodeSelectorPosition: { x: 0, y: 0 },
      selectedEdge: null,
      // 节点配置对话框相关状态
      nodeConfigDialogVisible: false,
      currentNodeData: {},
      nodeConfigPosition: { x: 0, y: 0 },
      // 导入对话框相关状态
      importDialogVisible: false,
      // 业务数据存储 - 以节点ID为key
      businessData: {},
      // 当前选中的节点ID
      selectedNodeId: null,
      // 位置选择相关状态
      locationInfo: null,
      defaultAddToGroup: false,
      showLocationSelector: false,
      locationSelectorPosition: { x: 0, y: 0 },
    }
  },
  computed: {
    currentZoom() {
      return this.graphManager ? this.graphManager.currentZoom : 1
    },
    selectedCount() {
      return this.graphManager ? this.graphManager.selectedCount : 0
    },
    locationSelectorStyle() {
      const x = Number(this.locationSelectorPosition.x) || 0
      const y = Number(this.locationSelectorPosition.y) || 0
      
      return {
        left: `${x + 10}px`,
        top: `${y + 20}px`
      }
    }
  },
      mounted() {
      this.initGraph()
      

    },
  methods: {
    /**
     * 初始化图形
     */
    initGraph() {
      // 初始化图形管理器
      this.graphManager = new GraphManager(document.getElementById('graph-container'))
      
      // 设置节点创建回调
      this.graphManager.onNodeCreated = (nodeId, initialData) => {
        this.businessData[nodeId] = initialData
      }
      
      // 初始化键盘管理器
      this.keyboardManager = new KeyboardManager(this.graphManager)
      
      // 设置对话框状态检查回调
      this.keyboardManager.setDialogVisibleCheck(() => this.nodeConfigDialogVisible)
      
             // 初始化拖拽管理器
       this.dragManager = new DragManager(this.graphManager)
       
             // 初始化布局管理器
      this.layoutManager = new LayoutManager(this.graphManager)
      
      // 设置布局管理器到图形管理器
      this.graphManager.setLayoutManager(this.layoutManager)
      
      // 添加示例节点
      SampleData.createSampleNodes(this.graphManager)
      
      // 监听图形管理器状态变化
      this.watchGraphManagerState()
      
      // 监听连线中间加号标签点击事件
      this.graphManager.graph.on('plus-icon-clicked', this.onPlusIconClicked)
      
      // 监听连线点击事件（用于+号标签点击）
      this.graphManager.graph.on('edge:click', ({ edge, e }) => {
        // 检查连线是否有+号标签
        if (edge.getData('hasPlusIcon')) {
          // 检查点击位置是否在标签附近
          const point = this.graphManager.graph.clientToLocal(e.clientX, e.clientY)
          const labels = edge.getLabels()
          
          if (labels && labels.length > 0) {
            const labelPosition = labels[0]
            const edgeBBox = edge.getBBox()
            
            // 计算标签的大概位置（连线中间）
            const labelX = edgeBBox.x + edgeBBox.width * 0.5
            const labelY = edgeBBox.y + edgeBBox.height * 0.5
            
            const distance = Math.sqrt(
              Math.pow(point.x - labelX, 2) + Math.pow(point.y - labelY, 2)
            )
            
            // 如果点击位置在标签附近（20像素范围内），触发+号点击事件
            if (distance <= 20) {
              // 优先使用鼠标事件位置
              let position = { x: 0, y: 0 }
              if (e && e.clientX !== undefined && e.clientY !== undefined) {
                position = { x: e.clientX, y: e.clientY }
              } else {
                // 如果没有鼠标事件，使用计算的中心位置
                const center = EdgeConfig.getEdgeCenter(edge)
                if (center) {
                  position = center
                }
              }
              // 获取位置信息
              const locationInfo = this.graphManager.getEdgeNodesLocation(edge)
              this.onPlusIconClicked({ edge, position, locationInfo })
              return
            }
          }
        }
      })
      
      // 监听节点点击事件
      this.graphManager.graph.on('node:click', ({ node, e }) => {
        // 弹出节点配置
        this.onNodeClick(node, e)
      })
      
      // 移除节点双击事件弹出节点配置
      // this.graphManager.graph.on('node:dblclick', ({ node, e }) => {
      //   this.onNodeClick(node, e)
      // })
    },

    /**
     * 监听图形管理器状态变化
     */
    watchGraphManagerState() {
      // 定期更新状态
      setInterval(() => {
        if (this.graphManager) {
          this.isDragging = this.graphManager.isDragging
          this.dragType = this.graphManager.dragType
          this.canUndo = this.graphManager.canUndo()
          this.canRedo = this.graphManager.canRedo()
        }
      }, 100)

      // 监听历史状态变化事件
      if (this.graphManager && this.graphManager.graph) {
        this.graphManager.graph.on('history:changed', () => {
          this.canUndo = this.graphManager.canUndo()
          this.canRedo = this.graphManager.canRedo()
        })
      }
    },

    /**
     * 切换抽屉显示状态
     */
    toggleDrawer() {
      this.drawerVisible = !this.drawerVisible
    },

    /**
     * 添加节点
     */
    addNode() {
      try {
        // 使用固定的颜色配置
        const nodeConfigs = [
          { color: '#5F95FF', fill: '#EFF4FF' },
          { color: '#52C41A', fill: '#F6FFED' },
          { color: '#FA8C16', fill: '#FFF7E6' },
          { color: '#F5222D', fill: '#FFF1F0' },
          { color: '#722ED1', fill: '#F9F0FF' }
        ]
        
        // 循环使用颜色配置
        const nodeIndex = this.graphManager.graph.getNodes().length
        const config = nodeConfigs[nodeIndex % nodeConfigs.length]
        
        const node = this.graphManager.addNode({
          x: Math.random() * 600 + 50,
          y: Math.random() * 400 + 50,
          width: 100,
          height: 50,
          label: '普通节点',
          attrs: {
            body: {
              stroke: config.color,
              strokeWidth: 2,
              fill: config.fill,
              rx: 8,
              ry: 8,
            },
            label: {
              fill: '#262626',
              fontSize: 14,
              fontWeight: 500,
            },
          },
          ports: this.graphManager.getBasePorts ? this.graphManager.getBasePorts() : {
            groups: {
              in: {
                position: 'left',
                attrs: {
                  circle: {
                    r: PORT_CONFIG.RADIUS,
                    magnet: PORT_CONFIG.MAGNET,
                    stroke: config.color,
                    strokeWidth: PORT_CONFIG.STROKE_WIDTH,
                    fill: PORT_CONFIG.FILL_COLOR,
                  },
                },
              },
              out: {
                position: 'right',
                attrs: {
                  circle: {
                    r: PORT_CONFIG.RADIUS,
                    magnet: PORT_CONFIG.MAGNET,
                    stroke: config.color,
                    strokeWidth: PORT_CONFIG.STROKE_WIDTH,
                    fill: PORT_CONFIG.FILL_COLOR,
                  },
                },
              },
            },
            items: [
              { group: 'in', id: 'in' },
              { group: 'out', id: 'out' },
            ],
          },
        })
        
        // 确保设置label属性
        node.attr('label/text', '普通节点')
        
        this.$message.success('节点添加成功')
        return node
      } catch (error) {
        this.$message.error('添加节点失败')
        console.error(error)
      }
    },

    /**
     * 根据类型添加节点
     */
    addNodeByType(type, label) {
      try {
        const center = this.graphManager.graph.getCenter()
        const node = this.graphManager.createNodeByType(type, label, center.x, center.y)
        
        // 确保设置label属性
        const nodeLabel = label || '普通节点'
        node.attr('label/text', nodeLabel)
        // 保持标签位置配置
        node.attr('label/position', {
          name: 'bottom',
          args: {
            y: 10,
          },
        })
        
        this.$message.success(`已添加 ${nodeLabel}`)
        return node
      } catch (error) {
        this.$message.error('添加节点失败')
        console.error(error)
      }
    },

    /**
     * 添加连线
     */
    addEdge() {
      try {
        this.graphManager.addRandomEdge()
        this.$message.success('连线添加成功')
      } catch (error) {
        this.$message.warning(error.message)
      }
    },

    /**
     * 全选
     */
    selectAll() {
      this.graphManager.selectAll()
      this.$message.success('已选择所有节点')
    },

    /**
     * 取消选择
     */
    clearSelection() {
      this.graphManager.clearSelection()
      this.$message.success('已取消选择')
    },

    /**
     * 删除选中元素
     */
    deleteSelected() {
      const selectedCells = this.graphManager.graph.getSelectedCells()
      if (selectedCells.length > 0) {
        // 过滤掉开始和结束节点，防止被删除
        const cellsToRemove = selectedCells.filter(cell => {
          if (cell.isNode()) {
            const label = cell.attr('label/text')
            return label !== '开始' && label !== '结束'
          }
          return true // 连线可以删除
        })
        
        if (cellsToRemove.length > 0) {
          // 删除节点时，同时删除对应的业务数据
          cellsToRemove.forEach(cell => {
            if (cell.isNode()) {
              const nodeId = cell.id
              if (this.businessData[nodeId]) {
                delete this.businessData[nodeId]
        
              }
            }
          })
          
          this.graphManager.graph.removeCells(cellsToRemove)
          this.graphManager.updateSelectedCount()
          
          // 检查是否需要自动连接开始和结束节点
          this.graphManager.checkAndConnectStartEnd()
          
          this.$message.success(`已删除 ${cellsToRemove.length} 个元素`)
          return cellsToRemove.length
        }
      }
      this.$message.warning('没有选中的元素')
      return 0
    },

    /**
     * 清空画布
     */
    clearGraph() {
      // 清空业务数据
      this.businessData = {}
      
      
      this.graphManager.clearGraph()
      this.$message.success('画布已清空')
    },

    /**
     * 撤销
     */
    undo() {
      try {
        this.graphManager.undo()
      } catch (error) {
        this.$message.error('撤销失败')
        console.error(error)
      }
    },

    /**
     * 重做
     */
    redo() {
      try {
        this.graphManager.redo()
      } catch (error) {
        this.$message.error('重做失败')
        console.error(error)
      }
    },

    /**
     * 居中显示
     */
    centerContent() {
      this.graphManager.centerContent()
      this.$message.success('画布已居中显示')
    },

    /**
     * 放大
     */
    zoomIn() {
      this.graphManager.zoomIn()
      this.$message.success(`放大成功，当前缩放: ${(this.currentZoom * 100).toFixed(0)}%`)
    },

    /**
     * 缩小
     */
    zoomOut() {
      this.graphManager.zoomOut()
      this.$message.success(`缩小成功，当前缩放: ${(this.currentZoom * 100).toFixed(0)}%`)
    },

    /**
     * 重置缩放
     */
    resetZoom() {
      this.graphManager.resetZoom()
      this.$message.success('缩放已重置')
    },

    /**
     * 导出SVG
     */
    async exportSVG() {
      try {
        await this.graphManager.exportSVG()
        this.$message.success('SVG导出成功')
      } catch (error) {
        this.$message.error('SVG导出失败')
      }
    },

    /**
     * 导出PNG
     */
    async exportPNG() {
      try {
        await this.graphManager.exportPNG()
        this.$message.success('PNG导出成功')
      } catch (error) {
        this.$message.error('PNG导出失败')
      }
    },

    /**
     * 导出JPEG
     */
    async exportJPEG() {
      try {
        await this.graphManager.exportJPEG()
        this.$message.success('JPEG导出成功')
      } catch (error) {
        this.$message.error('JPEG导出失败')
      }
    },

    /**
     * 返回首页
     */
    goHome() {
      this.$router.push('/')
    },

    /**
     * 显示快捷键说明
     */
    showShortcuts() {
      this.$info({
        title: '快捷键说明',
        content: h => h('div', {
          style: {
            textAlign: 'left',
            lineHeight: '1.6'
          }
        }, [
          h('p', [h('strong', '画布操作：')]),
          h('p', '• Ctrl + 滚轮：缩放画布'),
          h('p', '• Shift + 拖拽：平移画布'),
          h('p', '• Ctrl + 0：重置缩放'),
          h('p', '• Ctrl + +：放大'),
          h('p', '• Ctrl + -：缩小'),
          h('p', '• Ctrl + C：居中显示'),
          h('br'),
          h('p', [h('strong', '选择操作：')]),
          h('p', '• Ctrl + A：全选'),
          h('p', '• Ctrl + D：取消选择'),
          h('p', '• Delete / Backspace：删除选中元素'),
          h('br'),
          h('p', [h('strong', '撤销/重做：')]),
          h('p', '• Ctrl + Z：撤销'),
          h('p', '• Ctrl + Y：重做')
        ]),
        width: 400,
        okText: '知道了'
      })
    },

    /**
     * 设置连线类型
     */
    setEdgeType(type) {
      this.currentEdgeType = type
      this.graphManager.setEdgeType(type)
      this.$message.success(`连线类型已设置为 ${type}`)
    },

    /**
     * 根据主色调获取填充色
     */
    getFillColor(color) {
      const colorMap = {
        '#5F95FF': '#EFF4FF',
        '#52C41A': '#F6FFED',
        '#FA8C16': '#FFF7E6',
        '#F5222D': '#FFF1F0',
        '#722ED1': '#F9F0FF'
      }
      return colorMap[color] || '#EFF4FF'
    },

    /**
     * 处理连线中间加号图标点击事件
     */
    onPlusIconClicked({ edge, position, locationInfo }) {

      
      // 检查edge是否有效
      if (!edge || !edge.isEdge || !edge.isEdge()) {
        console.error('传入的edge无效')
        return
      }
      
      this.selectedEdge = edge
      this.locationInfo = locationInfo
      
      // 检查是否需要显示位置选择
      const { sourceInGroup, targetInGroup } = locationInfo || {}
      
      if (sourceInGroup && targetInGroup) {
        // 两端都在组内，默认添加到组内
        this.defaultAddToGroup = true
        this.showLocationSelector = false
        this.nodeSelectorPosition = {
          x: Number(position.x),
          y: Number(position.y)
        }
        this.nodeSelectorVisible = true
      } else if (sourceInGroup || targetInGroup) {
        // 一端在组内，一端在组外，需要用户选择
        this.showLocationSelector = true
        this.locationSelectorPosition = {
          x: Number(position.x),
          y: Number(position.y)
        }
      } else {
        // 两端都在组外，默认添加到组外
        this.defaultAddToGroup = false
        this.showLocationSelector = false
        this.nodeSelectorPosition = {
          x: Number(position.x),
          y: Number(position.y)
        }
        this.nodeSelectorVisible = true
      }
    },

    /**
     * 处理节点选择
     */
    onNodeSelected(selectedNode) {
      if (!this.selectedEdge) {
        return
      }

      try {
        // 如果是Group节点，使用特殊创建方法
        if (selectedNode.type === 'group-flow') {
          // 获取连线的中心位置
          const edgeCenter = EdgeConfig.getEdgeCenter(this.selectedEdge)
          if (!edgeCenter) {
            this.$message.error('无法获取连线中心位置')
            return
          }

          // 调整位置，让Group中心对齐到连线中心
          const groupX = edgeCenter.x - 200 // Group宽度的一半
          const groupY = edgeCenter.y - 150 // Group高度的一半

          // 获取原来连线上的源节点和目标节点
          const sourceId = this.selectedEdge.getSourceCellId()
          const targetId = this.selectedEdge.getTargetCellId()
          const sourceNode = this.graphManager.graph.getCellById(sourceId)
          const targetNode = this.graphManager.graph.getCellById(targetId)

          // 创建Group节点并初始化普通节点
          const result = this.graphManager.createGroupWithNode(
            groupX,
            groupY,
            selectedNode.nodeType,
            selectedNode.label,
            sourceNode,
            targetNode
          )
          
          const { group, newEdges } = result

          // 手动更新+号图标位置（使用新创建的连线）
          if (newEdges && newEdges.sourceToGroupEdge && newEdges.groupToTargetEdge) {
            setTimeout(() => {
              this.graphManager.updatePlusIconPosition(newEdges.sourceToGroupEdge)
              this.graphManager.updatePlusIconPosition(newEdges.groupToTargetEdge)
            }, 100)
          }

          this.$message.success(`已创建组节点并初始化${selectedNode.label}`)
        } else {
          // 获取连线的中心位置
          const edgeCenter = EdgeConfig.getEdgeCenter(this.selectedEdge)
          if (!edgeCenter) {
            this.$message.error('无法获取连线中心位置')
            return
          }

          // 获取节点配置以了解节点尺寸
          const color = NodeConfig.getFixedColor(selectedNode.type)
          const nodeConfig = NodeConfig.getNodeConfig(selectedNode.type, selectedNode.label, color)
          
          // 调整位置，让节点中心对齐到连线中心
          const nodeX = edgeCenter.x - (nodeConfig.width || 100) / 2
          const nodeY = edgeCenter.y - (nodeConfig.height || 50) / 2

          // 根据defaultAddToGroup决定是否添加到组内
          if (this.defaultAddToGroup) {
            // 添加到组内：找到相关的组节点
            const { sourceInGroup, targetInGroup } = this.locationInfo || {}
            let targetGroup = null
            
            if (sourceInGroup) {
              // 源节点在组内，找到源节点的父组
              const sourceId = this.selectedEdge.getSourceCellId()
              const sourceNode = this.graphManager.graph.getCellById(sourceId)
              if (sourceNode) {
                targetGroup = sourceNode.getParent()
              }
            } else if (targetInGroup) {
              // 目标节点在组内，找到目标节点的父组
              const targetId = this.selectedEdge.getTargetCellId()
              const targetNode = this.graphManager.graph.getCellById(targetId)
              if (targetNode) {
                targetGroup = targetNode.getParent()
              }
            }
            
            if (targetGroup && targetGroup.isNode()) {
              // 在组内创建节点
              const newNode = this.graphManager.createNodeByType(
                selectedNode.type,
                selectedNode.label,
                nodeX,
                nodeY
              )
              
              // 将节点添加到组内
              targetGroup.addChild(newNode)
              
              // 检查selectedEdge是否仍然有效
              if (!this.selectedEdge || !this.selectedEdge.isEdge || !this.selectedEdge.isEdge()) {
                console.error('selectedEdge无效或已被删除')
                this.$message.error('连线已失效，无法插入节点')
                return
              }
              
              // 获取连线的源节点和目标节点ID
              const sourceId = this.selectedEdge.getSourceCellId()
              const targetId = this.selectedEdge.getTargetCellId()
              
              // 使用 EdgeConfig 的插入节点方法，传递节点ID
              EdgeConfig.insertNodeInEdge(this.selectedEdge, newNode, this.graphManager, sourceId, targetId)
              
              this.$message.success(`已在组内插入 ${selectedNode.label}`)
            } else {
              // 如果找不到组，回退到普通创建
              this.createNodeInEdge(selectedNode, nodeX, nodeY)
            }
          } else {
            // 添加到组外
            this.createNodeInEdge(selectedNode, nodeX, nodeY)
          }
        }
      } catch (error) {
        this.$message.error('插入节点失败')
        console.error(error)
      } finally {
        this.nodeSelectorVisible = false
        this.selectedEdge = null
        this.locationInfo = null
        this.defaultAddToGroup = false
      }
    },

    /**
     * 关闭节点选择器
     */
    closeNodeSelector() {
      this.nodeSelectorVisible = false
      this.selectedEdge = null
    },

    /**
     * 选择添加到组内
     */
    selectAddToGroup() {
      this.defaultAddToGroup = true
      this.showLocationSelector = false
      this.nodeSelectorPosition = this.locationSelectorPosition
      this.nodeSelectorVisible = true
    },

    /**
     * 选择添加到组外
     */
    selectAddToOutside() {
      this.defaultAddToGroup = false
      this.showLocationSelector = false
      this.nodeSelectorPosition = this.locationSelectorPosition
      this.nodeSelectorVisible = true
    },

    /**
     * 关闭位置选择器
     */
    closeLocationSelector() {
      this.showLocationSelector = false
      this.selectedEdge = null
    },

    /**
     * 在连线中创建节点的辅助方法
     */
    createNodeInEdge(selectedNode, nodeX, nodeY) {
      // 检查selectedEdge是否仍然有效
      if (!this.selectedEdge || !this.selectedEdge.isEdge || !this.selectedEdge.isEdge()) {
        console.error('selectedEdge无效或已被删除')
        this.$message.error('连线已失效，无法插入节点')
        return
      }
      
      // 在连线中间创建新节点
      const newNode = this.graphManager.createNodeByType(
        selectedNode.type,
        selectedNode.label,
        nodeX,
        nodeY
      )

      // 获取连线的源节点和目标节点ID
      const sourceId = this.selectedEdge.getSourceCellId()
      const targetId = this.selectedEdge.getTargetCellId()
      
      // 使用 EdgeConfig 的插入节点方法，传递节点ID
      EdgeConfig.insertNodeInEdge(this.selectedEdge, newNode, this.graphManager, sourceId, targetId)

      this.$message.success(`已在连线中间插入 ${selectedNode.label}`)
    },

    /**
     * 处理节点点击事件
     */
    onNodeClick(node, event) {
      // 阻止事件冒泡和默认行为，防止双击事件透传到弹窗的 input 元素
      if (event) {
        event.preventDefault()
        event.stopPropagation()
      }
      
      // 获取节点ID
      const nodeId = node.id
      this.selectedNodeId = nodeId
      
      // 从单独的业务数据存储中获取数据
      const bizData = this.businessData[nodeId] || {}
      
      // 获取节点标签（优先业务数据的 label 或 groupSettings.label）
      const nodeLabel =
        bizData.label ||
        (bizData.groupSettings && bizData.groupSettings.label) ||
        node.attr('label/text') ||
        '普通节点'
      
      // 根据节点标签判断节点类型
      let nodeType = 'HttpV1' // 默认类型
      if (nodeLabel === '开始' || nodeLabel === '开始节点') {
        nodeType = 'start'
      } else if (nodeLabel === '结束' || nodeLabel === '结束节点') {
        nodeType = 'end'
      }
      
      // 组节点自动收集输入变量选项
      let inputVariableOptions = []
      if ((bizData.type || nodeType) === 'group' || node.shape === 'group') {
        const groupNode = node
        if (typeof groupNode.getChildren === 'function') {
          const children = groupNode.getChildren() || []

          const graph = this.graphManager.graph
          const seen = new Set()
          children.forEach(child => {
            const inEdges = graph.getIncomingEdges(child) || []

            inEdges.forEach(edge => {
              const source = edge.getSourceCell()

              if (source && source.id !== groupNode.id) {
                const outputs = (this.businessData[source.id]?.outputVariables) || []

                outputs.forEach(output => {
                  // 用 nodeName+name+type 做唯一性判断，确保不同节点的同名输出变量都能显示
                  const nodeName = source.attr && source.attr('label/text') || source.id
                  const key = nodeName + '|' + output.name + '|' + (output.type || '')
                  if (!seen.has(key)) {
                    seen.add(key)
                    inputVariableOptions.push({ 
                      ...output, 
                      nodeName,
                      nodeId: source.id, // 添加 nodeId 字段
                      outputName: output.name // 添加 outputName 字段用于显示
                    })
                  }
                })
              }
            })
          })

        }
      }
      this.currentNodeData = {
        id: nodeId, // 添加节点ID
        ...bizData, // 从业务数据存储中获取配置数据
        label: nodeLabel,
        type: bizData.type || nodeType, // 优先使用业务数据中的类型，否则使用推断的类型
        inputVariables: bizData.inputVariables || [],
        outputVariables: bizData.outputVariables || [],
        timeout: bizData.timeout || 30,
        httpConfig: bizData.httpConfig || {
          method: 'GET',
          url: '',
          headers: [],
          body: '',
          formData: [],
          activeTab: 'json'
        },
        // 新增：组节点自动收集的输入变量选项
        inputVariableOptions
      }
      
      // 使用鼠标点击的实际位置
      let clickX = 0
      let clickY = 0
      
      if (event && event.clientX !== undefined && event.clientY !== undefined) {
        // 使用鼠标点击位置
        clickX = event.clientX
        clickY = event.clientY
      } else {
        // 如果没有鼠标事件，使用节点中心位置作为备选
        const bbox = node.getBBox()
        const container = this.graphManager.graph.container
        const containerRect = container.getBoundingClientRect()
        const zoom = this.graphManager.graph.zoom()
        
        clickX = containerRect.left + (bbox.x + bbox.width / 2) * zoom
        clickY = containerRect.top + (bbox.y + bbox.height / 2) * zoom
      }
      
      // 延迟显示弹窗，防止双击事件透传
      setTimeout(() => {
        this.nodeConfigPosition = {
          x: clickX,
          y: clickY
        }
        this.nodeConfigDialogVisible = true
      }, 80)
    },

    /**
     * 处理节点配置保存
     */
    onNodeConfigSave(configData) {
      // 获取当前选中的节点
      const selectedNodes = this.graphManager.graph.getSelectedCells().filter(cell => cell.isNode())
      if (selectedNodes.length > 0) {
        const node = selectedNodes[0]
        const nodeId = node.id
        
        // 将业务数据保存到单独的业务数据存储中
        this.businessData[nodeId] = {
          ...(this.businessData[nodeId] || {}), // 保留现有的业务数据
          ...configData // 合并新的配置数据
        }
        
        // 更新节点标签显示
        const newLabel = configData.label || '普通节点'
        node.attr('label/text', newLabel)
        // 保持标签位置配置
        node.attr('label/position', {
          name: 'bottom',
          args: {
            y: 10,
          },
        })
        
        // 如果是组节点，自动生成左上角描述
        if ((configData.type || node.getData('type')) === 'group' || node.shape === 'group') {
          // 统计组内节点数量和类型
          let desc = ''
          if (typeof node.getChildren === 'function') {
            const children = node.getChildren() || []
            const typeMap = {}
            children.forEach(child => {
              const childData = child.getData && child.getData()
              const t = (childData && childData.type) || child.shape || '未知类型'
              typeMap[t] = (typeMap[t] || 0) + 1
            })
            const typeStr = Object.entries(typeMap).map(([k, v]) => `${k}:${v}`).join(' ')
            desc = `组内节点数:${children.length}${typeStr ? ' ' + typeStr : ''}`
          } else {
            desc = '组节点'
          }
          node.attr('desc/text', desc)
          

        }
        
        // 保存后主动更新相关连线的+号图标位置
        setTimeout(() => {
          this.graphManager.updateAllRelatedPlusIcons(node)
        }, 100)
        
        this.$message.success('节点配置已更新')
      }
      
      this.closeNodeConfigDialog()
    },

    /**
     * 关闭节点配置对话框
     */
    closeNodeConfigDialog() {
      this.nodeConfigDialogVisible = false
      this.currentNodeData = {}
      this.nodeConfigPosition = { x: 0, y: 0 }
    },

    /**
     * 自动布局
     */
    autoLayout() {
      try {
        this.layoutManager.autoLayout()
        this.$message.success('智能排版完成')
      } catch (error) {
        this.$message.error('自动排版失败')
        console.error(error)
      }
    },

    /**
     * 水平布局
     */
    horizontalLayout() {
      try {
        this.layoutManager.horizontalLayout()
        this.$message.success('水平布局完成')
      } catch (error) {
        this.$message.error('水平布局失败')
        console.error(error)
      }
    },

    /**
     * 垂直布局
     */
    verticalLayout() {
      try {
        this.layoutManager.verticalLayout()
        this.$message.success('垂直布局完成')
      } catch (error) {
        this.$message.error('垂直布局失败')
        console.error(error)
      }
    },

    /**
     * 树形布局
     */
    treeLayout() {
      try {
        this.layoutManager.treeLayout()
        this.$message.success('树形布局完成')
      } catch (error) {
        this.$message.error('树形布局失败')
        console.error(error)
      }
    },

    /**
     * 圆形布局
     */
    circularLayout() {
      try {
        this.layoutManager.circularLayout()
        this.$message.success('圆形布局完成')
      } catch (error) {
        this.$message.error('圆形布局失败')
        console.error(error)
      }
    },

    /**
     * 网格布局
     */
    gridLayout() {
      try {
        this.layoutManager.gridLayout()
        this.$message.success('网格布局完成')
      } catch (error) {
        this.$message.error('网格布局失败')
        console.error(error)
      }
    },

    /**
     * 序列化图形数据
     */
    serializeGraph() {
      try {
        // 获取图形数据
        const graphData = this.graphManager.graph.toJSON()
        
        // 整合画布内容和业务数据
        const completeData = {
          graph: graphData, // 画布内容
          businessData: this.businessData // 业务数据
        }
        
        // 添加调试信息
        
        
        // 序列化为JSON字符串
        const serializedData = JSON.stringify(completeData, null, 2)
        
        // 打印到控制台
  
        
        // 显示成功消息
        this.$message.success('图形数据已序列化并打印到控制台')
        
        // 可选：复制到剪贴板
        if (navigator.clipboard) {
          navigator.clipboard.writeText(serializedData).then(() => {
            this.$message.info('数据已复制到剪贴板')
          }).catch(() => {
            // 如果复制失败，静默处理
          })
        }
        
      } catch (error) {
        this.$message.error('序列化失败')
        console.error('序列化错误:', error)
      }
    },

    /**
     * 打开导入对话框
     */
    openImportDialog() {
      this.importDialogVisible = true
    },

    /**
     * 关闭导入对话框
     */
    closeImportDialog() {
      this.importDialogVisible = false
    },

    /**
     * 处理导入数据
     */
    handleImport(importedData) {
      try {
        // 清空当前画布
        this.graphManager.graph.clearCells()
        
        // 清空业务数据
        this.businessData = {}
        
        // 从导入的数据中恢复业务数据
        if (importedData.businessData) {
          this.businessData = importedData.businessData
        }
        
        // 从JSON数据恢复图形
        this.graphManager.graph.fromJSON(importedData.graph)
        
        // 重新绑定事件
        this.graphManager.bindEvents()
        
        // 重新添加+号图标到所有边
        const edges = this.graphManager.graph.getEdges()
        edges.forEach(edge => {
          // 检查边是否已经有+号图标
          const children = edge.getChildren()
          const existingPlusIcon = children.find(child => child.getData && child.getData('isPlusIcon'))
          
          // 如果没有+号图标，才添加
          if (!existingPlusIcon) {
            this.graphManager.addPlusIconToEdge(edge)
          }
        })
        
        // 居中显示内容
        this.centerContent()
        
        // 关闭导入对话框
        this.closeImportDialog()
        
        this.$message.success('数据导入成功！')
        
      } catch (error) {
        console.error('导入错误:', error)
        this.$message.error('导入失败，请检查数据格式')
      }
    },

  },
  beforeDestroy() {
    // 销毁所有管理器
    if (this.keyboardManager) {
      this.keyboardManager.dispose()
    }
    if (this.dragManager) {
      this.dragManager.dispose()
    }
    if (this.graphManager) {
      this.graphManager.dispose()
    }
    if (this.layoutManager) {
      this.layoutManager.dispose()
    }
  }
}
</script>

<style scoped>
.graph-container {
  height: 100%;
}

/* 位置选择器样式 */
.location-selector-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 9999;
}

.location-selector {
  position: fixed;
  background: white;
  border-radius: 6px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15), 0 4px 12px rgba(0, 0, 0, 0.1);
  min-width: 180px;
  overflow: hidden;
  border: 1px solid #e8e8e8;
  z-index: 10000;
}

.selector-header {
  padding: 8px 12px;
  background: #fafafa;
  border-bottom: 1px solid #e8e8e8;
}

.selector-title {
  font-size: 12px;
  color: #666;
  font-weight: 500;
}

.selector-content {
  padding: 4px 0;
}

.selector-item {
  display: flex;
  align-items: center;
  padding: 8px 12px;
  cursor: pointer;
  transition: background-color 0.2s ease;
  user-select: none;
}

.selector-item:hover {
  background-color: #f5f5f5;
}

.selector-item:active {
  background-color: #e6f7ff;
}

.item-icon {
  width: 16px;
  height: 16px;
  margin-right: 8px;
  border: 1px solid #d9d9d9;
  border-radius: 2px;
  position: relative;
  flex-shrink: 0;
}

.group-icon {
  background-color: #f0f8ff;
  border-color: #5F95FF;
  border-radius: 3px;
}

.group-icon::after {
  content: '⊞';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 8px;
  color: #5F95FF;
  font-weight: bold;
}

.outside-icon {
  background-color: #f6ffed;
  border-color: #52C41A;
  border-radius: 3px;
}

.outside-icon::after {
  content: '○';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 8px;
  color: #52C41A;
  font-weight: bold;
}

.item-text {
  font-size: 13px;
  color: #333;
  flex: 1;
}

/* 画布容器样式 */
#graph-container {
  background: #fafafa;
  border-radius: 4px;
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
}

/* 抽屉样式 */
.ant-drawer {
  position: absolute !important;
  z-index: 1000;
}

.ant-drawer-mask {
  display: none !important;
}

.ant-drawer-content-wrapper {
  position: absolute !important;
  box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15);
  background: #fff;
  border-right: 1px solid #e8e8e8;
}

.ant-drawer-content {
  background: #fff;
}

/* +号图标样式 */
.plus-icon {
  transition: all 0.2s ease;
}

.plus-icon:hover {
  transform: scale(1.1);
  filter: drop-shadow(0 4px 8px rgba(0,0,0,0.15));
}

/* 连线标签样式优化 */
.x6-edge-label {
  pointer-events: auto;
  cursor: pointer;
}

.x6-edge-label:hover {
  opacity: 0.8;
}
</style> 